package server.valves;
import server.HttpResponse;
import server.Request;
import server.Response;
import server.ValveContext;
import server.connector.http.Constants;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Locale;
import java.util.Properties;

/*
Host容器的阀,是默认的错误处理器,如果请求处理出错且未给该状态码配备转发uri,将使用该处理器返回给客户端简单的错误提示信息
*/
/*
2023/3/24 该类内容全部写完,后续直接使用,无需修改
by cyl
 */
public class ErrorReportValve extends ValveBase {
    private static final String info = "server.valves.ErrorReportValve/1.0";
    private static Properties properties = new Properties();
    static {
        String path = System.getProperty("user.dir") + File.separator + "src" + File.separator + "server" + File.separator + "valves" + File.separator + "ErrorReport.properties";
        try {
            properties.load(new FileInputStream(path));
        } catch (Exception e) {
            System.out.println("读取错误信息文件失败");
        }

    }
    @Override
    public String getInfo() {
        return info;
    }

    @Override
    public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException {
        context.invokeNext(request, response);

        HttpServletRequest hrequest = (HttpServletRequest)request.getRequest();
        HttpServletResponse hresponse = (HttpServletResponse)response.getResponse();

        //已经提交响应,无法再改变内容
        if (hresponse.isCommitted())
            return;
//        response.setSuspended(true);
        try {
            Throwable throwable = (Throwable) request.getRequest().getAttribute("javax.servlet.error.exception");
            report(request, response, throwable);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    private void report(Request request, Response response, Throwable throwable) {
        HttpServletRequest hrequest = (HttpServletRequest)request.getRequest();
        HttpServletResponse hresponse = (HttpServletResponse)response.getResponse();
        int status = hresponse.getStatus();
        String message = ((HttpResponse)response).getMessage();
        if (message == null)
            message = "";
        //正常状态码不用调整
        if (status < 400)
            return;

        Throwable rootCause = null;
        if (throwable != null) {
            if (throwable instanceof ServletException)
                rootCause = ((ServletException) throwable).getRootCause();
        }
        StringBuffer sb = new StringBuffer();
        String report = properties.getProperty("http." + status, "error").replace("{0}", message);

        sb.append("<html><head><title>");
        sb.append(Constants.SERVER_INFO);
        sb.append("</title>");
        sb.append("<STYLE><!--");
        sb.append("H1{font-family : sans-serif,Arial,Tahoma;color : white;background-color : #0086b2;} ");
        sb.append("H3{font-family : sans-serif,Arial,Tahoma;color : white;background-color : #0086b2;} ");
        sb.append("BODY{font-family : sans-serif,Arial,Tahoma;color : black;background-color : white;} ");
        sb.append("B{color : white;background-color : #0086b2;} ");
        sb.append("HR{color : #0086b2;} ");
        sb.append("--></STYLE> ");
        sb.append("</head><body>");
        sb.append("<h1>");
        sb.append("HTTP Status " + status + " - " + message + "</h1>");
        sb.append("<HR size=\"1\" noshade>");
        sb.append("<p><b>type</b> ");
        if (throwable != null) {
            sb.append("Exception report");
        } else {
            sb.append("Status report");
        }
        sb.append("</p>");
        sb.append("<p><b>");
        sb.append("message");
        sb.append("</b> <u>");
        sb.append(message).append("</u></p>");
        sb.append("<p><b>");
        sb.append("description");
        sb.append("</b> <u>");
        sb.append(report);
        sb.append("</u></p>");

        if (throwable != null) {
            StringWriter stackTrace = new StringWriter();
            throwable.printStackTrace(new PrintWriter(stackTrace));
            sb.append("<p><b>");
            sb.append("exception");
            sb.append("</b> <pre>");
            sb.append(stackTrace.toString());
            sb.append("</pre></p>");
            if (rootCause != null) {
                stackTrace = new StringWriter();
                rootCause.printStackTrace(new PrintWriter(stackTrace));
                sb.append("<p><b>");
                sb.append("root cause");
                sb.append("</b> <pre>");
                sb.append(stackTrace.toString());
                sb.append("</pre></p>");
            }
        }

        sb.append("<HR size=\"1\" noshade>");
        sb.append("<h3>").append(Constants.SERVER_INFO + " @VERSION@1.0</h3>");
        sb.append("</body></html>");

        try {
            PrintWriter writer = hresponse.getWriter();
            hresponse.setContentType("text/html");
            hresponse.setLocale(Locale.getDefault());
            writer.write(sb.toString());
            writer.flush();
        } catch (Throwable t) {

        }

    }

}
